


-- handler function
CREATE FUNCTION plproxy_call_handler ()
RETURNS language_handler AS '$libdir/plproxy' LANGUAGE C;

-- language
CREATE LANGUAGE plproxy HANDLER plproxy_call_handler;



CREATE LANGUAGE plpgsql;
CREATE SCHEMA plproxy;


CREATE TABLE plproxy.conf (
    cluster_name text,
    host text,
    port text,
    dbname text,
    username text
);
CREATE INDEX idx_cluster_username_plproxy ON plproxy.conf USING btree (cluster_name);

CREATE TABLE plproxy.cluster_name (
   cluster_name text,
   pid int
);



CREATE OR REPLACE FUNCTION plproxy.get_cluster_config(i_cluster_name text, OUT o_key text, OUT o_val text)
 RETURNS SETOF record
AS $$
BEGIN
  o_key := 'connection_lifetime';
  o_val := 30*60;
  RETURN NEXT;
  RETURN;
END;
$$ LANGUAGE plpgsql;


CREATE OR REPLACE FUNCTION plproxy.get_cluster_partitions(i_cluster_name text)
RETURNS SETOF text
AS $$
DECLARE
    r record;
BEGIN
    FOR r IN
        SELECT 'host=' || host || ' port=' || port || ' dbname=' || dbname || ' user=' || username AS connect_string
        FROM plproxy.conf
        WHERE cluster_name = i_cluster_name
        ORDER BY dbname
    LOOP
        RETURN NEXT r.connect_string;
    END LOOP;
    IF NOT FOUND THEN
        RAISE EXCEPTION 'no such cluster: %', i_cluster_name;
    END IF;
    RETURN;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;


CREATE OR REPLACE FUNCTION plproxy.get_cluster_version(i_cluster_name text)
RETURNS integer
AS $$
    SELECT 21;
$$ LANGUAGE sql;



CREATE OR REPLACE FUNCTION plproxy.set_default_cluster_name (cluster_name text)
RETURNS text AS $$
DELETE FROM plproxy.cluster_name WHERE pid = 0;
INSERT INTO plproxy.cluster_name VALUES($1, 0);
SELECT $1;
$$ LANGUAGE SQL;


CREATE OR REPLACE FUNCTION plproxy.set_cluster_name(cluster_name text)
RETURNS text AS $$
DELETE FROM plproxy.cluster_name WHERE pid = pg_backend_pid();
INSERT INTO plproxy.cluster_name VALUES($1, pg_backend_pid());
SELECT $1;
$$ LANGUAGE SQL;


CREATE OR REPLACE FUNCTION plproxy.get_cluster_name()
 RETURNS text AS $$
SELECT cluster_name 
  FROM plproxy.cluster_name
 WHERE pid = pg_backend_pid() 
    OR pid = 0 
ORDER BY pid DESC
 LIMIT 1;
$$ LANGUAGE SQL;


CREATE OR REPLACE FUNCTION plproxy.clear_cluster_name() 
RETURNS void AS $$
DELETE FROM plproxy.cluster_name WHERE pid = pg_backend_pid();
$$ LANGUAGE SQL;



CREATE OR REPLACE FUNCTION public.ddlexec(stmt text)
RETURNS SETOF integer
    AS $$
CLUSTER plproxy.get_cluster_name();
RUN ON ALL;
$$ LANGUAGE plproxy;


CREATE OR REPLACE FUNCTION public.ddlexec_and_query(stmt text, query text)
RETURNS setof record AS $$
CLUSTER plproxy.get_cluster_name();
RUN ON ALL;
$$ LANGUAGE plproxy;


CREATE OR REPLACE FUNCTION public.dquery(stmt text)
RETURNS setof record AS $$
CLUSTER plproxy.get_cluster_name();
RUN ON ALL;
$$ LANGUAGE plproxy;


CREATE OR REPLACE FUNCTION public.dquery_single(query text, node integer)
RETURNS SETOF record
AS $$
CLUSTER plproxy.get_cluster_name();
RUN ON cast(node as int);
$$ LANGUAGE plproxy;

CREATE OR REPLACE FUNCTION public.dquery_single(query text, bcookie text)
RETURNS SETOF record
AS $$
CLUSTER plproxy.get_cluster_name();
RUN ON hashtext(bcookie);
$$ LANGUAGE plproxy;


